#include <data.hpp>
#include <fstream>
#include <vector>
#include <str.hpp>
#include <cmath>        // for nan("")
#include <baltam.hpp>

bxArray* readdata(
    const std::string &filename,
    const std::string &delimiter,
    bool leading,
    bool collapse,
    size_t num
) {
    // std::ifstream 输入文件流, 用于从文件读取信息
    // std::ios::in 打开文件用于读取
    std::ifstream file(filename, std::ios::in);
    if (!file.is_open()) {
        std::string info = "找不到或无法打开 '" + filename + "'. 请检查路径和文件名或文件权限";
        bxErrMsgTxt(info.c_str());
    }

    std::string line;
    // 跳过标题行
    for (size_t i = 0; i < num; i++) {
        if (!std::getline(file, line)) {
            break;
        }
    }

    std::vector<std::vector<double>> data;
    std::vector<std::string> line_strings;
    baSize col = 0;         // 矩阵列数

    // std::istream& getline(std::istream&, std::string&) 返回流对象
    // 通过检查返回的流状态判断操作是成功
    while (std::getline(file, line)) {
        // 去掉行首分隔符
        if (leading) {
            line = trimLeadingDelimiters(line, delimiter);
        }
        // 分割字符串
        line_strings = split(line, delimiter, collapse);
        // 跳过空行数据
        if (line_strings.size() == 1 && line_strings[0].empty()) {
            continue;
        }

        std::vector<double> line_data;
        for (const std::string& s: line_strings) {
            // double std::stod(const std::string&, size_t*, int = 10)
            // 将字符串转换为双精度浮点数 (double), 字符串可以空格, 正负号, 以及数字开头
            // 其他字符开头无法转换, std::invalid_arguments 错误
            double value;
            try {
                value = std::stod(s);
            } catch (std::invalid_argument) {
                value = nan("");
            }
            line_data.push_back(value);
        }

        data.push_back(line_data);
        // 更新最大列数
        col = line_data.size() > col ? line_data.size() : col;
    }
    file.close();

    baSize row = data.size();       // 矩阵行数
    if (row == 0) {
        return bxCreateDoubleMatrix(0, 0, bxREAL);
    } else {
        return vector2BALTAM(data, row, col);
    }
}
